﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

namespace Universe.WCF.Behaviors
{
    public class DeliveryDictionary
    {
        object Sync = new object();
        private MessageHeaders _headers = null;

        internal DeliveryDictionary(MessageHeaders headers)
        {
            _headers = headers;
        }

        public bool Contains(string name)
        {
            lock (Sync)
            {
                int index;
                return Contains(name, out index);
            }
        }

        private bool Contains(string name, out int index)
        {
            lock (Sync)
            {
                int i = 0;
                foreach (var info in _headers)
                {
                    if (info.Name == name && info.Namespace == TransparentDeliveryInspector.HeaderNamespace)
                    {
                        index = i;
                        return true;
                    }
                    i++;
                }

                index = -1;
                return false;
            }
        }

        public void Set<T>(string name, T value)
        {
            lock (Sync)
            {
                int index;
                bool contains = Contains(name, out index);
                if (contains)
                    _headers.RemoveAt(index);

                MessageHeader h = MessageHeader.CreateHeader(name, TransparentDeliveryInspector.HeaderNamespace, value);
                _headers.Add(h);
            }
        }

        public T Get<T>(string name)
        {
            lock (Sync)
            {
                if (Contains(name))
                {
                    try
                    {
                        T tt = _headers.GetHeader<T>(name, TransparentDeliveryInspector.HeaderNamespace);
                        return tt;
                    }
                    catch (Exception ex)
                    {
                        ExceptionDetail ed = new ExceptionDetail(ex);
                        throw new FaultException<ExceptionDetail>(
                            ed,
                            string.Format("Failed to Get Header '{0}' of type [{1}]", name, typeof (T).Name)
                            );
                    }
                }
                else
                    return default(T);
            }
        }
    }
}
